package cn.wgx.modules.sys.services;

import cn.wgx.commons.annotation.RequestCache;
import cn.wgx.commons.util.*;
import cn.wgx.modules.base.services.BaseService;
import cn.wgx.modules.sys.entity.SysUser;
import cn.wgx.modules.sys.entity.SysUserExample;
import cn.wgx.modules.sys.entity.dto.DTOSysUser;
import cn.wgx.modules.sys.entity.mapper.SysUserMapper;
import cn.wgx.modules.sys.entity.shortentity.ShortSysUser;
import cn.wgx.modules.sys.util.CityUtil;
import cn.wgx.modules.sys.util.UserTypeUtil;
import cn.wgx.modules.sys.util.UserUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static cn.wgx.modules.sys.util.UserUtil.USER_CACHE;

@Service
public class SysUserService extends BaseService<SysUser> {

    @Resource
    SysUserMapper sysUserMapper;

    @Autowired
    SysLogService sysLogService;

    private static final SysUser emptyUser = new SysUser();

    static {
        emptyUser.setUser_id(-1);
        emptyUser.setUsername("nobody");
        emptyUser.setNickname("未指定");
    }

    /**
     * 登录
     * @param user
     * @param rememberMe
     */
    public void getlogin(SysUser user, boolean rememberMe) {
        Subject sb = SecurityUtils.getSubject();
        UsernamePasswordToken up = new UsernamePasswordToken(user.getUsername(), user.getMima(), true);
        sb.login(up);
    }

    //登出
    public void logout() {
        Subject sb = SecurityUtils.getSubject();
        sb.logout();
    }

    @Transactional(readOnly = true)
    public List<SysUser> getListByIds(List<Integer> ids) {
        if(ids == null || ids.isEmpty()){
            return emptyList;
        }
        List<Integer> uniList = getUniList(ids);
        if(!uniList.isEmpty()){
            SysUserExample example = new SysUserExample();
            SysUserExample.Criteria criteria = example.createCriteria();
            criteria.andUser_idIn(uniList);
            List<SysUser> eduCourseAssignmentHis = sysUserMapper.selectByExample(example);
            return eduCourseAssignmentHis;
        }
        return null;
    }

    @RequestCache
    public  SysUser getUserByIdHasMima(Integer id, boolean flush){
        SysUser sysUser = null;
        if(flush){
            //数据库取值
            sysUser = getSysUserById(id + "", true, true );
            if(sysUser != null){
                UserUtil.setCache(sysUser);
            }else{
                UserUtil.clearSecondCache(id);
            }
        }else{
            //缓存取值
            sysUser = (SysUser) CacheUtils.get(UserUtil.USER_CACHE, UserUtil.USER_CACHE_ID_ + id);
            if (sysUser ==  null){
                //数据库取值
                sysUser = getSysUserById(id + "", true, true );
                if (sysUser != null){
                    UserUtil.setCache(sysUser);
                }else{
                    return null;
                }
            }else {
                return sysUser;
            }
        }
        return sysUser;
    }
    /**
     * 检测用户名是否占用,true可注册
     * @param username
     * @return
     */
    public boolean checkUsername(String username) {
        SysUser sysUser = getSysUserByUsername(username, false, false);
        if(sysUser == null){
            return true;
        }
        return false;
    }
    /**
     * 检测手机号码是否可用,true 可用
     * @param phone
     * @return
     */
    public boolean checkPhone(String phone) {
        SysUser sysUser = getSysUserByPhone(phone, false);
        if(sysUser == null){
            return true;
        }
        return false;
    }
    /**
     * 检测邮箱是否可用,true 可用
     * @param email
     * @return
     */
    public boolean checkPEmail(String email) {
        SysUser sysUser = getSysUserByEmail(email, false);
        if(sysUser == null){
            return true;
        }
        return false;
    }
    /**
     * 根据ID查询用户
     * @param id
     * @param needMima
     * @return
     */
    public SysUser getSysUserById(String id, boolean needMima, boolean isNotLock) {
        return getSysUserByType(id, "id", needMima, isNotLock);
    }
    /**
     * 根据用户名查询用户
     * @param username
     * @param needMima
     * @return
     */
    public SysUser getSysUserByUsername(String username, boolean needMima, boolean isLock) {
        return getSysUserByType(username, "username", needMima, isLock);
    }

    /**
     * 根据Email查询用户
     * @param email
     * @param needMima
     * @return
     */
    public SysUser getSysUserByEmail(String email, boolean needMima) {
        return getSysUserByType(email, "email", false, false);
    }
    /**
     * 根据phone查询用户
     * @param phone
     * @param needMima
     * @return
     */
    public SysUser getSysUserByPhone(String phone, boolean needMima) {
        return getSysUserByType(phone, "phone", false, false);
    }
    /**
     * 通用查询
     * @param param
     * @param type
     * @param needMima
     * @param isNotLock 是否检测正常状态,true检测,false不检测.状态(0:正常,1:锁定,2解锁,3永久锁定)
     * @return
     */
    private SysUser getSysUserByType(String param, String type, boolean needMima, boolean isNotLock) {
        if(null == param){ return emptyUser;}
        SysUserExample sysUserExample = new SysUserExample();
        SysUserExample.Criteria criteria = sysUserExample.createCriteria();
        switch(type){
            case "email": criteria.andEmailEqualTo(param);break;
            case "username": criteria.andUsernameEqualTo(param);break;
            case "phone": criteria.andPhoneEqualTo(param);break;
            case "id": criteria.andUser_idEqualTo(Integer.parseInt(param));break;
            default: criteria.andUser_idEqualTo(-1);
        }
        if(isNotLock){
            //状态(0:正常,1:锁定,2解锁,3永久锁定)
            criteria.andStatusNotEqualTo(1);//不等于1,3
            criteria.andStatusNotEqualTo(3);
            //删除状态
            criteria.andIs_deleteEqualTo(0);
        }
        List<SysUser> list = sysUserMapper.selectByExample(sysUserExample);
        if(!needMima){
            getUserFilter(list);
        }
        if(list != null && list.size()>0){
            List<? extends SysUser> wrap = wrap(list);
//            List<DTOSysUser> dtoList = wrap(list);
//            addCityName(dtoList);
            return wrap.get(0);
        }
        return null;
    }

//    public List<DTOSysUser> turnDTO(List<SysUser> sysUsers){
//        List<DTOSysUser> list = new ArrayList<>();
//        for(SysUser sysUser: sysUsers){
//            DTOSysUser dtoSysUser = turnDTO(sysUser);
//            list.add(dtoSysUser);
//        }
//        addCityName(list);
//        return  list;
//    }
    //包装
    public DTOSysUser wrap(SysUser sysUser){
        DTOSysUser dtoSysUser = new DTOSysUser();
        BeanUtils.copyProperties(sysUser, dtoSysUser);
        String cityId = sysUser.getCity();
        String provinceId = sysUser.getProvince();
        if(NumberUtils.isDigits(cityId)){//添加城市中文
            dtoSysUser.set_cityName(CityUtil.getName(Integer.parseInt(cityId)));
        }
        if(NumberUtils.isDigits(provinceId)){//添加省中文
            dtoSysUser.set_provinceName(CityUtil.getName(Integer.parseInt(provinceId)));
        }
        return dtoSysUser;
    }

    public ShortSysUser turnShortUser(SysUser sysUser){
        ShortSysUser dtoSysUser = new ShortSysUser();
        BeanUtils.copyProperties(sysUser, dtoSysUser);
        return dtoSysUser;
    }

    public List<ShortSysUser> turnShortUser(List<SysUser> sysUser){
        List<ShortSysUser> list = Lists.newArrayList();
        for(SysUser sysUser1: sysUser){
            list.add(turnShortUser(sysUser1));
        }
        return list;
    }
//    public List<DTOSysUser> wrap(List<SysUser> sysUsers){
//        List<DTOSysUser> dtoSysUsers = Lists.newArrayList();
//        for(SysUser sysUser: sysUsers){
//            dtoSysUsers.add(wrap(sysUser));
//        }
//        return dtoSysUsers;
//    }


    /**
     *
     * @param record
     * @param order
     * @return
     */
    public List<SysUser> getList(SysUser record, String title , String order) {
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        if(null != record){
            if(StringUtils.isNotBlank(record.getUsername())){
                criteria.andUsernameLike("%"+record.getUsername()+"%");
            }
            if(StringUtils.isNotBlank(record.getNickname())){
                criteria.andNicknameLike("%"+record.getNickname()+"%");
            }
            if(record.getType() != null){
                criteria.andTypeEqualTo(record.getType());
            }
            if(record.getCity() != null){
                criteria.andCityEqualTo(record.getCity());
            }
            if(record.getEmail() != null){
                criteria.andEmailEqualTo(record.getEmail());
            }
            if(record.getPhone() != null){
                criteria.andPhoneEqualTo(record.getPhone());
            }
            if(record.getSex() != null){
                criteria.andSexEqualTo(record.getSex());
            }
            if(record.getRole_id() != null){
                criteria.andRole_idEqualTo(record.getRole_id());
            }
            if(record.getIs_delete() == null){
                criteria.andIs_deleteEqualTo(0);
            }else{
                criteria.andIs_deleteNotEqualTo(0);
            }
            StringBuffer schoolUserSql = new StringBuffer( "t.user_id in (select user_id from edu_school_user where ");
            boolean hasSchoolSql = false;
            if(hasSchoolSql){
                schoolUserSql.append(") and 1=");
                addCustomSQL(criteria, schoolUserSql.toString(), "1");
            }
        }
        if(("desc".equals(order) || "asc".equals(order)) && EnumUtils.isValidEnum(SysUser.Column.class, title)){
            example.setOrderByClause(title + " " + order);
        }else{
            example.setOrderByClause("type asc, user_id asc");
        }
        List<SysUser> records = sysUserMapper.selectByExample(example);
        getUserFilter(records);
        return (records);
    }

    /**
     * 新增用户
     * @param record
     * @return
     */
    @Transactional
    public SysUser insertOne(SysUser record) {
        filter(record, true);
        int i = sysUserMapper.insertSelective(record);
        if(i>0){
            afterNewUser(record);
        }
        getUserFilter(record);
        return record;
    }

    private void afterNewUser(SysUser record){
        EMailUtil.sendSimpleEMail(record.getEmail(), "教育平台 - 注册成功","您的账号: " + record.getUsername() + ", 已注册成功. 登录地址: http://file.sxycy.cn:90");

    }

    @Transactional
    public int updateOne(SysUser record, boolean filter) {
        if(filter) filter(record,false);
        int i = sysUserMapper.updateByPrimaryKeySelective(record);
        if ( i> 0 ) {
            UserUtil.clearSecondCache(record.getUser_id());
        }
        return i;
    }

    /**
     * 更新用户状态
     * @param record
     * @return
     */
    @Transactional
    public int updateStatus(SysUser record) {
        SysUser sysUser = new SysUser();
        sysUser.setUser_id(record.getUser_id());
        sysUser.setStatus(record.getStatus());
        int n = sysUserMapper.updateByPrimaryKeySelective(sysUser);
        if (n > 0) {
            //清除缓存中的数据
            UserUtil.clearSecondCache(record.getUser_id());
        }
        return n;

    }
    /**
     * 更新数据不过滤,慎用.
     * @param sysUser
     * @return
     */
    @Transactional
    public int updateNoFilter(SysUser sysUser){
        return sysUserMapper.updateByPrimaryKeySelective(sysUser);
    }

    /**
     * 改密码
     * @param sysUser
     * @return
     */
    @Transactional
    public int updatePassword(SysUser sysUser, String oldPassword, String newPassword) {
        SysUser sysUser1 = new SysUser();
        sysUser1.setMima(MD5(newPassword, sysUser.getUsername()));
        //encodePassword(sysUser1);
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        if(oldPassword != null){//已登录用户修改密码
            criteria.andMimaEqualTo(MD5(oldPassword, sysUser.getUsername()));
            criteria.andUser_idEqualTo(sysUser.getUser_id());
        }else{//未登录用户
            if(sysUser.getEmail() != null){
                criteria.andEmailEqualTo(sysUser.getEmail());
            }else if(sysUser.getPhone() != null){
                criteria.andPhoneEqualTo(sysUser.getPhone());
            }else{
                return 0;
            }
        }
        return sysUserMapper.updateByExampleSelective(sysUser1,example);
    }

    /**
     * 重置密码为账号
     * @param username
     * @return
     */
    @Transactional
    public int resetPass(String username) {
        SysUser sysUser1 = new SysUser();
        sysUser1.setMima(MD5(username, username));
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        criteria.andUsernameEqualTo(username);
        return sysUserMapper.updateByExampleSelective(sysUser1,example);
    }
    /**
     * 绑定手机号
     * @param sysUser
     * @return
     */
    @Transactional
    public int bindPhone(SysUser sysUser) {
        SysUser sysUser1 = new SysUser();
        sysUser1.setUser_id(sysUser.getUser_id());
        sysUser1.setPhone(sysUser.getPhone());
        sysUser1.setPhoneCheck(true);
        return sysUserMapper.updateByPrimaryKeySelective(sysUser1);
    }

    @Transactional
    public int deleteOne(Integer id) {
        SysUserExample sysUserExample = new SysUserExample();
        sysUserExample.createCriteria().andUser_idEqualTo(id);
        SysUser sysUser1 = new SysUser();
        sysUser1.setIs_delete(1);
        sysUser1.setStatus(3);
        int r = sysUserMapper.updateByExampleSelective(sysUser1, sysUserExample);
//        int r = sysUserMapper.deleteByPrimaryKey(id);
        return r;
    }


    /**
     * 初始化新增或修改用户信息
     * 密码加密,日期初始化
     * @param sysUser
     */
    protected void filter(SysUser sysUser, boolean insert){
        //设置初始数据为0,避免提交变化
//        sysUser.setFansNum(null);
//        sysUser.setFavoriteNum(null);
//        sysUser.setHeatNum(null);
//        sysUser.setPoints(null);
//        sysUser.setTheamNum(null);
//        sysUser.setStorageSize(null);
//        sysUser.setReviewNum(null);
        //手机已绑定标志
        sysUser.setStatus(null);
        if(insert){
            encodePassword(sysUser);
            //注册必须获取邮箱验证码,所以已绑定
//            sysUser.setEmailCheck(true);
            if(Validation.isMobile(sysUser.getPhone())){
                sysUser.setPhoneCheck(true);
            }else{
                sysUser.setPhoneCheck(null);
            }
            //邮箱已绑定标志
            if(Validation.isEmail(sysUser.getEmail())){
                sysUser.setEmailCheck(true);
            }else{
                sysUser.setEmailCheck(null);
            }
            if(StringUtils.isBlank(sysUser.getPhoto()) || sysUser.getPhoto().startsWith("string")){
                sysUser.setPhoto(null);
            }
            sysUser.setStatus(null);
            sysUser.setIs_delete(null);
        }else{
            //不可修改字段
            sysUser.setUsername(null);
            sysUser.setMima(null);
            sysUser.setPhoneCheck(null);
            sysUser.setEmailCheck(null);
            sysUser.setRole_id(null);
            sysUser.setIs_delete(null);
            sysUser.setStatus(null);
            sysUser.setType(null);
            sysUser.setSalt(null);
//            sysUser.setNickname(null);
        }

        super.filter(sysUser, insert);
    }


    public JSONObject getCount(Date startDate,Date endDate) {

        JSONObject jsonObject = new JSONObject();
        Page page = PageHelper.startPage(1,1);
        SysUserExample example = new SysUserExample();
        sysUserMapper.selectByExample(example);
        jsonObject.put("all", page.getTotal());//用户总数

        Page page2 = PageHelper.startPage(1,1);
        SysUserExample.Criteria criteria = example.createCriteria();
        criteria.andCreateDateGreaterThanOrEqualTo(DateUtils.getDateZero());

        sysUserMapper.selectByExample(example);
        jsonObject.put("todayNew", page2.getTotal());//今日新增

        int activeCount = sysLogService.getTodayActiveUserCount();
        jsonObject.put("todayActive", activeCount);//今日活跃用户

        List<Map> list = sysLogService.getCountActive(DateUtils.getDateZero(),null);
        if(list != null && list.size()>0){
            jsonObject.put("todayClick", list.get(0).get("c"));//今日点击数
        }else{
            jsonObject.put("todayClick", 0);
        }

        if(startDate == null && endDate == null){
            startDate = DateUtils.plusDay(new Date(), -30);
        }else if(startDate != null && endDate == null){
            endDate = DateUtils.plusDay(startDate, 30);
        }else if(startDate == null && endDate != null){
            startDate = DateUtils.plusDay(endDate, -30);
        }else if(endDate.getTime() - startDate.getTime() > 2592000000l){ //时间间隔最大30天
            endDate = DateUtils.plusDay(startDate, 30);
        }
        List<Map> listBetweenDate = sysLogService.getCountActive(startDate,endDate);
        jsonObject.put("count", listBetweenDate);

        return jsonObject;
    }

    /**
     * 密码加密
     * @param sysUser
     */
    private void encodePassword(SysUser sysUser){
        String mima = sysUser.getMima();
        String paymima = sysUser.getPayMima();
        if(mima != null && !mima.equals("") && sysUser.getUsername() != null){
            sysUser.setMima(MD5(mima,sysUser.getUsername()));
            sysUser.setSalt(sysUser.getUsername());
        }
        if(paymima != null && !paymima.equals("") && sysUser.getUsername() != null){
            sysUser.setPayMima(MD5(paymima,sysUser.getUsername()));
            sysUser.setSalt(sysUser.getUsername());
        }
    }

    /**
     * 阻止初始化学校数据
     * @param list
     */
    public static List<SysUser> doNotIni(List<SysUser> list){
        if(list == null){
            return emptyList;
        }
        int n = list.size();
        for(int i=0;i<n;i++){
            SysUser sysUser = list.get(i);
        }
        return list;
    }

    public static SysUser doNotIni(SysUser list){
        if(list == null){
            return list;
        }
        return list;
    }
    /**
     * 返回用户过滤器,防止密码返回
     * @param list
     */
    public static void getUserFilter(List<SysUser> list){
        if(list == null){
            return;
        }
        int n = list.size();
        for(int i=0;i<n;i++){
            SysUser sysUser = list.get(i);
            getUserFilter(sysUser);
        }
    }
    public static void getUserFilter(SysUser sysUser){
        if(sysUser==null)return;
        sysUser.setPayMima(null);
        sysUser.setMima(null);
        sysUser.setSalt(null);
    }

    private String MD5(String p, String salt){
        return new Md5Hash(p,salt).toString();
    }

    public int updateRole(Integer user_id, String rold_id) {
        SysUser sysUser1 = new SysUser();
        sysUser1.setUser_id(user_id);
        sysUser1.setRole_id(rold_id);
        sysUser1.setType(Integer.parseInt(rold_id));
        return sysUserMapper.updateByPrimaryKeySelective(sysUser1);
    }

    public String getNewTeacherName(String schoolCode){
        return getNewUserName(schoolCode, 1);
    }

    public String getNewStudentName(String schoolCode){
        return getNewUserName(schoolCode, 2);
    }

    public String getNewUserName(String schoolCode, int type){
        String d = DateUtils.getDate().substring(2).replaceAll("-","");
        String pre = schoolCode + d;
        if(type == 1){
            pre = "T" + pre;
        }else if(type == 2){
            pre = "S" + pre;
        }
        SysUserExample example = new SysUserExample();
        example.createCriteria().andUsernameLike(pre+"%");
        example.setOrderByClause("userName desc");
        PageHelper.startPage(1,1);
        List<SysUser> sysUsers = sysUserMapper.selectByExample(example);
        if(sysUsers.isEmpty()){
            return pre + "0001";
        }else{
            SysUser sysUser = sysUsers.get(0);
            String username = sysUser.getUsername();
            String substring = username.substring(username.length() - 4);
            if(NumberUtils.isDigits(substring)){
                int i = Integer.parseInt(substring);
                i++;
                String newid = String.format("%04d", i);
                return pre + newid;
            }
        }
        return null;
    }
}